/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.je.bpm.engine.impl.cmd;

import com.google.common.base.Strings;
import com.je.bpm.core.model.BpmnModel;
import com.je.bpm.core.model.FlowElement;
import com.je.bpm.core.model.config.ProcessRemindTypeEnum;
import com.je.bpm.engine.ActivitiException;
import com.je.bpm.engine.impl.context.Context;
import com.je.bpm.engine.impl.identity.Authentication;
import com.je.bpm.engine.impl.interceptor.Command;
import com.je.bpm.engine.impl.interceptor.CommandContext;
import com.je.bpm.engine.impl.persistence.entity.TaskEntity;
import com.je.bpm.engine.impl.persistence.entity.UrgeLogEntity;
import com.je.bpm.engine.impl.persistence.entity.UrgeLogEntityImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 催办命令
 */
public class UrgeTaskCmd implements Command<Void>, Serializable {

    private static final Logger logger = LoggerFactory.getLogger(UrgeTaskCmd.class);

    /**
     * 主送
     */
    private static final String MAIN_SEND = "MAIN_SEND";
    /**
     * 抄送
     */
    private static final String COPY_SEND = "COPY_SEND";

    private String taskId;
    private List<String> reminderMethod;
    private List<Map<String, String>> personBeingUrged;
    private String urgentContent;
    private List<Map<String, String>> ccUser;
    private String ccContent;
    private String currentNodeId;
    private String funcCode;
    private String beanId;
    private String from;
    private String fromName;

    public UrgeTaskCmd(List<String> reminderMethod, List<Map<String, String>> personBeingUrged, String urgentContent,
                       List<Map<String, String>> ccUser, String ccContent, String taskId, String currentNodeId, String funcCode) {
        this.taskId = taskId;
        this.reminderMethod = reminderMethod;
        this.personBeingUrged = personBeingUrged;
        this.urgentContent = urgentContent;
        this.ccUser = ccUser;
        this.ccContent = ccContent;
        this.currentNodeId = currentNodeId;
        this.funcCode = funcCode;
    }


    @Override
    public Void execute(CommandContext commandContext) {
        TaskEntity task = commandContext.getProcessEngineConfiguration().getTaskEntityManager().findById(taskId);
        if (task == null) {
            throw new ActivitiException("Can't find the task.");
        }
        beanId = task.getBusinessKey();
        BpmnModel bpmnModel = commandContext.getProcessEngineConfiguration().getRepositoryService().getBpmnModel(task.getProcessDefinitionId());
        FlowElement flowElement = bpmnModel.getFlowElement(task.getTaskDefinitionKey());
        if (flowElement == null) {
            throw new ActivitiException("Can't find the flow element in the definition.");
        }

        from = Authentication.getAuthenticatedUser().getDeptId();
        fromName = Authentication.getAuthenticatedUser().getName();
        String pdid = task.getProcessDefinitionId();
        String piid = task.getProcessInstanceId();
        String processName = bpmnModel.getMainProcess().getName();
        String taskName = task.getName();
        List<UrgeLogEntity> addUrgeLogEntity = new ArrayList<>();
        for (Map<String, String> user : personBeingUrged) {
            String userId = user.get("id");
            if (Strings.isNullOrEmpty(userId)) {
                continue;
            }
            String userName = user.get("userName");
            UrgeLogEntity urgeLogEntity = insertUrgeLogEntity(pdid, piid, processName, taskName, MAIN_SEND, userId,
                    userName, urgentContent, "催办");
            addUrgeLogEntity.add(urgeLogEntity);
        }

        for (Map<String, String> user : ccUser) {
            String userId = user.get("id");
            if (Strings.isNullOrEmpty(userId)) {
                continue;
            }
            String userName = user.get("userName");
            UrgeLogEntity urgeLogEntity = insertUrgeLogEntity(pdid, piid, processName, taskName, COPY_SEND, userId,
                    userName, ccContent, "抄送");
            addUrgeLogEntity.add(urgeLogEntity);
        }

        return null;
    }


    private UrgeLogEntity insertUrgeLogEntity(String pdid, String piid, String processName, String taskName, String type,
                                              String to, String toName, String content, String name) {
        Date nowDate = new Date();
        UrgeLogEntity mainUrgeLogEntity = new UrgeLogEntityImpl();
        mainUrgeLogEntity.setProcessInstanceId(piid);
        mainUrgeLogEntity.setProcessDefinitionId(pdid);
        mainUrgeLogEntity.setProcessName(processName);
        mainUrgeLogEntity.setTaskId(taskId);
        mainUrgeLogEntity.setTaskName(taskName);
        mainUrgeLogEntity.setFrom(from);
        mainUrgeLogEntity.setFromName(fromName);
        mainUrgeLogEntity.setTo(to);
        mainUrgeLogEntity.setToName(toName);
        mainUrgeLogEntity.setCreateTime(nowDate);
        mainUrgeLogEntity.setReadState("0");
        mainUrgeLogEntity.setReadTime(null);
        mainUrgeLogEntity.setNodeId(currentNodeId);
        mainUrgeLogEntity.setContent(content);
        mainUrgeLogEntity.setReminderType(type);
        mainUrgeLogEntity.setReminderName(name);
        List<String> reminderMethodNames = new ArrayList<>();
        for (String code : reminderMethod) {
            reminderMethodNames.add(ProcessRemindTypeEnum.getType(code).getName());
        }
        mainUrgeLogEntity.setReminderMethodCode(String.join(",", reminderMethod));
        mainUrgeLogEntity.setReminderMethodName(String.join(",", reminderMethodNames));
        Context.getCommandContext().getProcessEngineConfiguration().getUrgeLogEntityManager().insert(mainUrgeLogEntity);
        remind(mainUrgeLogEntity, reminderMethod);
        return mainUrgeLogEntity;
    }

    private void remind(UrgeLogEntity urgeLogEntity, List<String> reminderMethod) {
        Context.getCommandContext().getProcessEngineConfiguration().getActivitiUpcomingRun()
                .pushUrge(beanId, funcCode, urgeLogEntity, reminderMethod);
    }

}
